home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
emulator
/
bsvc-1.000
/
bsvc-1
/
bsvc-1.0.4
/
src
/
Assemblers
/
hecasm
/
lex.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-07-26
|
9KB
|
439 lines
#include "asm.h"
#include "global.h"
vtype token; /* token parsed from expression */
vtype opq[SRCMAX]; /* queue of tokens */
int optop; /* head pointer for the queue */
int undefined; /* true when an expression contained an */
/* undefined symbol */
/* evaluate an expression and take care of all the flags and stuff to */
/* assign it to a symbol. This is called for statements like "a = b + 1" */
/* sp is a pointer to the symbol in the ust where the information */
/* is to be stored */
evaluate(sp)
struct sym *sp;
{
/* no undefined symbols in the expression yet */
undefined = FALSE;
/* initialize the queue */
optop = 0;
/* create a postfix image of the expression in opq */
eval();
/* evaluate the image */
sp->s_value = post();
/* some symbol was undefined making this symbol undefined */
if (undefined)
sp->s_type |= S_ABS;
else
if (pass)
/* on the first pass make it just defined */
sp->s_type |= S_DEF;
else
/* on the second pass make it valid */
sp->s_type |= S_VALID;
}
/* evaluate an expression and return the result */
expr()
{
int val;
/* initialize the front of the queue */
optop = 0;
/* create a tokenized postfix image of the expression */
eval();
/* evaluate it */
val = post();
return(val);
}
/* this function gets the next symbol or value in the source buffer */
/* tokenizes it an returns it */
lexan()
{
char id[NCPS];
int t;
struct sym *p;
/* get a character */
t = getnb();
/* the next object must be a number */
if (isdigit(t))
{
/* get the string of digits evaluate it an enter it as a token */
getid(t,id);
token.uval.ival = numconv(id);
token.type = NUM;
return(NUM);
}
else if (alpha(t))
{
/* it must be a symbol */
getid(t,id);
/* give it a pointer to its record in the ust */
token.uval.sval = ustlookup(id);
token.type = ID;
return(ID);
}
else if (t == '\'')
{
/* it must be a character constant */
token.uval.ival = getmap();
token.type = NUM;
if (getnb() != '\'')
err('h',"illegal character constant");
return(NUM);
}
else if (t == '\0')
{
/* end of line */
return(DONE);
}
else
{
/* must be an operator */
return(validop(t));
}
}
/* use lexan & emit to tokenize an expression and put it in opq */
eval()
{
int tos;
optype stack[STSIZE], c;
/* reset the operator - operand stack */
tos = 0;
/* evaluate the expression */
while((c.val = lexan()) != DONE && c.val != NONE)
{
/* term gets an arithmetic term this might be "1" or "symbol" */
/* or "-1" or "!symbol" etc. It also gets the next token */
/* from the source text */
if ((c.val = term(c.val)) == DONE || c.val == NONE)
{
/* almost done, perform everything on the stack */
while(tos != 0)
emit(stack[tos--].val);
return;
}
/* get the precedence of the operator */
c.pr = preced(c.val);
/* keep operators on the stack in ascending precedence to assure */
/* correct association */
if((c.pr > stack[tos].pr) || (tos == 0))
{
/* push the operator */
stack[++tos] = c;
/* do the next operator */
continue;
}
/* start evaluating into the stack until something of lower */
/* precedence than the one in temporary storage is found */
for(;;)
{
emit(stack[tos--]);
/* if the stack is empty stop */
if(tos == 0)
break;
/* the precedence of the operation on top of the stack is */
/* high enough then shift things around and keep going */
if (c.pr > stack[tos].pr)
break;
}
stack[++tos] = c;
}
err('M',"missing operand");
return(c.val);
}
/* get a term as described above */
term(tok)
int tok;
{
int nc;
/* act on the token passed here */
switch(tok)
{
/* open parenthesies */
/* a parenthesized expression is treated as a single term therefore */
/* eval is called recursively */
case OP:
if (eval() == NONE)
{
if ((tok = getnb()) != ')')
{
err(')',"missing right parentheses");
putback(tok);
}
}
else
err(')',"missing right parentheses");
break;
/* negative sign */
case MI:
term(lexan());
emit(NE);
break;
/* complement '~' */
case CO:
term(lexan());
emit(CO);
break;
/* negate '!' */
case NG:
term(lexan());
emit(NG);
break;
/* a number */
case NUM:
emit(NUM);
break;
/* a symbol */
case ID:
emit(ID);
break;
/* this one is wrong so try another */
default:
err('t',"missing expression term");
term(lexan());
}
/* get the next token */
nc = lexan();
if (nc == OP)
{
/* this would make an invalid expression */
putback('(');
nc = DONE;
}
return(nc);
}
/* convert a number represented as a string in decimal, hexadecimal, octal */
/* or binary form to an integer */
numconv(str)
char *str;
{
int res;
/* the second character tells the base */
/* hex - 0x00 */
/* oct - 0o00 */
/* bin - 0b00 */
/* dec - 0d00 or 00 */
switch(*(str+1))
{
/* hex */
case 'x':
{
/* leading 0 */
if (*str != '0')
{
err('H',"improper hex format");
return(0);
}
else
/* get the value */
if (!sscanf((str+2),"%x",&res))
err('H',"improper hex format");
return(res);
}
case 'o':
{
/* leading 0 */
if (*str != '0')
{
err('O',"improper octal format");
return(0);
}
else
/* get the value */
if (!sscanf((str+2),"%o",&res))
err('O',"improper octal format");
return(res);
}
case 'b':
{
/* leading 0 */
if (*str != '0')
{
err('B',"improper binary format");
return(0);
}
else
/* get the value */
{
res = 0;
str++;
/* shift on every charater and add one when the char is '1' */
while (*++str != '\0')
{
res = res << 1;
if (*str == '1')
res++;
else
/* not a zero or a one */
if (*str != '0')
{
err('B',"improper binary format");
return(0);
}
}
}
return(res);
}
case 'd' :
{
/* leading 0 */
if (*str != '0')
{
err('D',"improper decimal format");
return(0);
}
else
/* get the value */
if (!sscanf((str+2),"%d",&res))
err('D',"improper decimal format");
return(res);
}
}
/* if the base was not explicitly specified then evaluate according */
/* to the default */
switch (radix)
{
case OCT:
/* get the value */
if(!sscanf(str,"%o",&res))
err('O',"improper octal format");
return(res);
case DEC:
if(!sscanf(str,"%d",&res))
err('D',"improper decimal format");
return(res);
case HEX:
if(!sscanf(str,"%x",&res))
err('H',"improper hex format");
return(res);
case BIN:
/* get the value */
res = 0;
/* shift on every charater and add one when the char is '1' */
while (*str != '\0')
{
res = res << 1;
if (*str == '1')
res++;
else
/* not a zero or a one */
if (*str != '0')
{
err('B',"improper binary format");
return(0);
}
str++;
}
return(res);
}
}
/* return the precedence of an operator */
preced(c)
int c;
{
switch(c)
{
case PL:
case MI:
return(12);
case MU:
case DI:
case MO:
return(13);
case AN:
return(8);
case OR:
return(6);
case XO:
return(7);
default:
err('p',"missing operator");
return(NONE);
}
}
/* return the token for an operator */
validop(c)
int c;
{
switch (c)
{
case '+':
return(PL);
case '-':
return(MI);
case '*':
return(MU);
case '/':
return(DI);
case '%':
return(MO);
case '&':
return(AN);
case '|':
return(OR);
case '^':
return(XO);
case '(':
return(OP);
case '~':
return(CO);
case '!':
return(NG);
default:
putback(c);
return(NONE);
}
}